/* implements userscript support */
import settings from './util/settings/settings.js';
import webviews from './webviews.js';
// import bangsPlugin from './navbar/searchbar/bangsPlugin.js';
import searchbar from './navbar/searchbar/searchbar.js';
import urlParser from './util/urlParser.js';

function parseTampermonkeyFeatures(content) {
  var parsedFeatures = {};
  var foundFeatures = false;

  var lines = content.split('\n');

  var isInFeatures = false;
  for (var i = 0; i < lines.length; i++) {
    if (lines[i].trim() === '// ==UserScript==') {
      isInFeatures = true;
      continue;
    }
    if (lines[i].trim() === '// ==/UserScript==') {
      isInFeatures = false;
      break;
    }
    if (isInFeatures && lines[i].startsWith('//')) {
      foundFeatures = true;
      var feature = lines[i].replace('//', '').trim();
      var featureName = feature.split(' ')[0];
      var featureValue = feature.replace(featureName + ' ', '').trim();
      featureName = featureName.replace('@', '');

      // special case: find the localized name for the current locale
      if (
        featureName.startsWith('name:') &&
        featureName.split(':')[1].substring(0, 2) ===
          navigator.language.substring(0, 2)
      ) {
        featureName = 'name:local';
      }
      if (parsedFeatures[featureName]) {
        parsedFeatures[featureName].push(featureValue);
      } else {
        parsedFeatures[featureName] = [featureValue];
      }
    }
  }
  if (foundFeatures) {
    return parsedFeatures;
  } else {
    return null;
  }
}

// checks if a URL matches a wildcard pattern
function urlMatchesPattern(url, pattern) {
  var idx = -1;
  var parts = pattern.split('*');
  for (var i = 0; i < parts.length; i++) {
    idx = url.indexOf(parts[i], idx);
    if (idx === -1) {
      return false;
    }
    idx += parts[i].length;
  }
  return idx !== -1;
}

const userscripts = {
  scripts: [], // {options: {}, content}
  loadScripts: function () {
    userscripts.scripts = [];

    var path = window.require('path');
    var scriptDir = path.join(window.globalArgs['home'], 'userscripts');

    fs.readdir(scriptDir, function (err, files) {
      if (err || files.length === 0) {
        return;
      }

      // store the scripts in memory
      files.forEach(function (filename) {
        if (filename.endsWith('.js')) {
          fs.readFile(
            path.join(scriptDir, filename),
            'utf-8',
            function (err, file) {
              if (err || !file) {
                return;
              }

              var domain = filename.slice(0, -3);
              if (domain.startsWith('www.')) {
                domain = domain.slice(4);
              }
              if (!domain) {
                return;
              }

              var tampermonkeyFeatures = parseTampermonkeyFeatures(file);
              if (tampermonkeyFeatures) {
                var scriptName =
                  tampermonkeyFeatures['name:local'] ||
                  tampermonkeyFeatures['name'];
                if (scriptName) {
                  scriptName = scriptName[0];
                } else {
                  scriptName = filename;
                }
                userscripts.scripts.push({
                  options: tampermonkeyFeatures,
                  content: file,
                  name: scriptName,
                });
              } else {
                // legacy script
                if (domain === 'global') {
                  userscripts.scripts.push({
                    options: {
                      match: ['*'],
                    },
                    content: file,
                    name: filename,
                  });
                } else {
                  userscripts.scripts.push({
                    options: {
                      match: ['*://' + domain],
                    },
                    content: file,
                    name: filename,
                  });
                }
              }
            }
          );
        }
      });
    });
  },
  getMatchingScripts: function (src) {
    return userscripts.scripts.filter(function (script) {
      if (
        (!script.options.match && !script.options.include) ||
        (script.options.match &&
          script.options.match.some((pattern) =>
            urlMatchesPattern(src, pattern)
          )) ||
        (script.options.include &&
          script.options.include.some((pattern) =>
            urlMatchesPattern(src, pattern)
          ))
      ) {
        if (
          !script.options.exclude ||
          !script.options.exclude.some((pattern) =>
            urlMatchesPattern(src, pattern)
          )
        ) {
          return true;
        }
      }
    });
  },
  runScript: function (tabid, script) {
    if (urlParser.isInternalURL(tabs.get(tabid).url)) {
      return;
    }
    webviews.callAsync(tabid, 'executeJavaScript', [
      script.content,
      false,
      null,
    ]);
  },
  onPageLoad: function (tabid) {
    console.log("onPageLoad")
    if (userscripts.scripts.length === 0) {
      return;
    }

    var src = tabs.get(tabid).url;

    userscripts.getMatchingScripts(src).forEach(function (script) {
      // TODO run different types of scripts at the correct time
      if (
        !script.options['run-at'] ||
        script.options['run-at'].some((i) =>
          [
            'document-start',
            'document-body',
            'document-end',
            'document-idle',
          ].includes(i)
        )
      ) {
        userscripts.runScript(tabid, script);
      }
    });
  },
  initialize: function () {
    settings.listen('userscriptsEnabled', function (value) {
      console.log("userscriptsEnabled changed")
      if (value === true) {
        userscripts.loadScripts();
      } else {
        userscripts.scripts = [];
      }
    });
    webviews.bindEvent('dom-ready', userscripts.onPageLoad);

    // bangsPlugin.registerCustomBang({
    //   phrase: '!run',
    //   snippet: l('runUserscript'),
    //   isAction: false,
    //   showSuggestions: function (text, input, event) {
    //     searchbar.reset('bangs');

    //     var isFirst = true;
    //     userscripts.scripts.forEach(function (script) {
    //       if (script.name.toLowerCase().startsWith(text.toLowerCase())) {
    //         searchbar.addResult('bangs', {
    //           title: script.name,
    //           fakeFocus: isFirst && text,
    //           click: function () {
    //             // tabEditor.hide();
    //             tabBar.hide_drop();
    //             userscripts.runScript(tabs.getSelected(), script);
    //           },
    //         });
    //         isFirst = false;
    //       }
    //     });
    //   },
    //   fn: function (text) {
    //     if (!text) {
    //       return;
    //     }
    //     var matchingScript = userscripts.scripts.find((script) =>
    //       script.name.toLowerCase().startsWith(text.toLowerCase())
    //     );
    //     if (matchingScript) {
    //       userscripts.runScript(tabs.getSelected(), matchingScript);
    //     }
    //   },
    // });
  },
};

export default userscripts;
